package com.example.demo.service;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
@Slf4j
public class WebSocketServer {

    private static int PORT = 8086;

    @Autowired
    private WebSocketQueue webSocketQueue;
    public void start() {

        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap
                    //设置主从线程
                    //parentGroup（bossGroup），负责处理客户端连接请求(accept 事件)
                    //childGroup(workerGroup)，负责处理已建立连接的I/O读写事件
                    .group(bossGroup, workerGroup)
                    //指定服务端通道类型，决定底层传输协议
                    .channel(NioServerSocketChannel.class)
                    //使用 PooledByteBufAllocator 减少内存复制
                    .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                    //为每个新连接初始化处理器链
                    .childHandler(new ChannelInitializer<NioSocketChannel>() {
                        @Override
                        protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                            nioSocketChannel.pipeline()
                                    //自定义心跳机制handler
                                    .addLast(new WebSocketIdleStateHandler())
                                    //http协议编解码器，用于处理http请求和响应的编码和解码。其主要作用是将http请求和响应消息转换为netty的ByteBuf对象，并将其传递到下一个处理器进行处理
                                    .addLast(new HttpServerCodec())
                                    //用于http服务端，将来自客户端的http请求和响应消息聚合成一个完整的消息
                                    .addLast(new HttpObjectAggregator(65536))
                                    //用于对websokcet消息进行压缩和解压缩操作
                                    .addLast(new WebSocketServerCompressionHandler())
                                    //可以对整个websocket通信进行初始化以及握手处理
                                    .addLast(new WebSocketServerProtocolHandler("/ws"))
                                    //自定义handler
                                    .addLast(new WebSocketHandler(webSocketQueue));
                        }
                    });

            ChannelFuture future = bootstrap.bind(PORT).sync();
            log.info("服务端启动成功 port: {}", PORT);
            future.channel().closeFuture().sync();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    @PostConstruct
    public void init() {
         new Thread(()->{
             try {
                 start();
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }).start();
    }

    public String getQueueDetail() {
        return webSocketQueue.getQueueDetails();
    }
}
